from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, session, current_app
from flask_login import login_user, logout_user, current_user, login_required
from datetime import datetime
from datetime import datetime, timedelta
from socket import timeout

bp = Blueprint('auth', __name__)


from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, session
from flask_login import login_user, current_user
from ..services import user_service

bp = Blueprint('auth', __name__)

@bp.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('main.index'))

    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        remember = True if request.form.get('remember') else False

        # 登录频率限制检查（每分钟最多5次尝试）
        redis_client = current_app.redis_client
        ip_key = f"login:ip:{request.remote_addr}"
        attempts = redis_client.incr(ip_key)
        redis_client.expire(ip_key, 60)  # 设置60秒过期

        if attempts > 5:
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify({
                    'success': False,
                    'message': '尝试次数过多，请稍后再试'
                }), 429
            flash('尝试次数过多，请稍后再试')
            return redirect(url_for('auth.login'))

        user = user_service.authenticate_user(username, password)

        if not user:
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify({
                    'success': False,
                    'message': '用户名或密码错误'
                }), 401
            flash('用户名或密码错误')
            return redirect(url_for('auth.login'))

        # 记录登录信息到Redis
        user_key = f"user:login:{user.id}"
        redis_client.hincrby(user_key, "login_count", 1)
        redis_client.hset(user_key, "last_login", datetime.now().isoformat())
        redis_client.expire(user_key, 86400 * 30)  # 保留30天数据

        login_user(user, remember=remember)

        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return jsonify({
                'success': True,
                'user': {
                    'id': user.id,
                    'username': user.username
                }
            }), 200

        session['user_id'] = user.id
        flash('登录成功')
        return redirect(url_for('main.index'))

    return render_template('login.html')


@bp.route('/api/check_auth')
@login_required
def check_auth():
    redis_client = current_app.redis_client
    user_key = f"auth:session:{current_user.id}"

    try:
        # 获取并处理Redis数据
        session_data = redis_client.hgetall(user_key)
        decoded_data = {
            key.decode('utf-8') if isinstance(key, bytes) else key:
                value.decode('utf-8') if isinstance(value, bytes) else value
            for key, value in session_data.items()
        }

        # 更新活跃时间（确保过期时间为整数）
        with redis_client.pipeline() as pipe:
            pipe.hset(user_key, "active_at", datetime.now().isoformat())
            pipe.expire(user_key, int(timedelta(days=30).total_seconds()))  # 关键修复：使用timedelta
            pipe.execute()

        return jsonify({
            'authenticated': True,
            'user': {
                'id': current_user.id,
                'username': current_user.username,
                'session': {
                    'login_count': int(decoded_data.get('login_count', 0)),
                    'last_login': decoded_data.get('last_login', ''),
                    'ip': decoded_data.get('ip', ''),
                    'active_at': decoded_data.get('active_at', '')
                }
            }
        })

    except Exception as e:
        current_app.logger.error(f"检查认证失败: {str(e)}", exc_info=True)
        return jsonify({
            'authenticated': False,
            'error': '无法获取会话信息'
        }), 500

@bp.route('/logout')
@login_required
def logout():
    session.pop('user_id', None)
    logout_user()
    flash('您已退出登录')
    return redirect(url_for('auth.login'))


@bp.route('/register', methods=['GET', 'POST'])
def register():
    if current_user.is_authenticated:
        return redirect(url_for('main.index'))

    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')

        # 只传递user_service.create_user()支持的参数
        user_data = {
            'username': username,
            'password': password,
            'is_admin': False
        }

        # 如果服务支持其他字段，可以添加
        if hasattr(user_service.create_user, 'email'):
            user_data['email'] = request.form.get('email')
        if hasattr(user_service.create_user, 'phone'):
            user_data['phone'] = request.form.get('phone')

        try:
            user = user_service.create_user(**user_data)
            if user:
                flash('注册成功，请登录！', 'success')
                return redirect(url_for('auth.login'))
            else:
                flash('注册失败，邮箱可已存在', 'error')
        except Exception as e:
            flash('注册失败,用户名已经存在','error')

    return render_template('register.html')


@bp.route('/forgot_password', methods=['GET', 'POST'])
def forgot_password():
    if current_user.is_authenticated:
        return redirect(url_for('main.index'))

    if request.method == 'POST':
        # 获取表单数据
        username = request.form.get('username')
        user_id = request.form.get('user_id')
        new_password = request.form.get('new_password')
        confirm_password = request.form.get('confirm_password')

        # 验证输入
        if not all([username, user_id, new_password, confirm_password]):
            flash('所有字段都必须填写', 'error')
            return redirect(url_for('auth.forgot_password'))

        if new_password != confirm_password:
            flash('两次输入的密码不一致', 'error')
            return redirect(url_for('auth.forgot_password'))

        # 尝试重置密码
        try:
            user_id = int(user_id)  # 转换为整数
            success = user_service.reset_password_with_username_and_id(
                username=username,
                user_id=user_id,
                new_password=new_password
            )

            if success:
                flash('密码重置成功，请使用新密码登录', 'success')
                return redirect(url_for('auth.login'))
            else:
                flash('用户名与用户ID不匹配或密码重置失败', 'error')
        except ValueError:
            flash('用户ID必须是数字', 'error')
        except Exception as e:
            flash(f'密码重置失败: {str(e)}', 'error')

    return render_template('forgot_password.html')
